Skip to content

Add the ability to declare empty item operations#3079

Merged
soyuka merged 3 commits into
api-platform:masterfrom
soyuka:feature/empty-item-operations
Sep 21, 2019
Merged

Add the ability to declare empty item operations#3079
soyuka merged 3 commits into
api-platform:masterfrom
soyuka:feature/empty-item-operations

Conversation

@soyuka

@soyuka soyuka commented Sep 18, 2019

Copy link
Copy Markdown
Member
Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #3051
License MIT
Doc PR na

Comment thread src/Action/PlaceholderAction.php Outdated
* @return object
*/
public function __invoke($data)
public function __invoke($data = null)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I maybe do a new controller instead of changing this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a new one that directly throw a 404 (so we can simplify the metadata).


$resourceMetadata = $resourceMetadata->withItemOperations($this->createOperations($methods));
} else {
if (!$itemOperations) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must explicitly check for a get operation (only PUT could be defined for instance).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can this be done without links to the Router? I can move the method guess from ApiLoader to metadata first, but when using a route_name, we won't be able to check the method without retrieving the route from the RouteCollection right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when using a route_name, we won't be able to check the method without retrieving the route from the RouteCollection right?

Applying the 80/20 rule, I'd say let's do nothing when we encounter such edge cases?

$resourceMetadata = $resourceMetadata->withItemOperations($this->createOperations($methods));
} else {
if (!$itemOperations) {
$itemOperations = ['placeholder' => ['method' => 'GET', 'read' => false, 'serialize' => false, 'status' => 404]];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The operation name should be get instead of placeholder.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use 'output' => false here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to be able to differentiate the get operation but sure can do!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be able to differentiate the get operation

I know. I'm against that. 😆

I think there should be nothing special about it. Just a good / safe default when the get item operation is missing.

@soyuka
soyuka force-pushed the feature/empty-item-operations branch from 373c57a to 57236d6 Compare September 20, 2019 07:20
Comment thread src/Action/NotFoundAction.php Outdated
{
public function __invoke()
{
return new Response(null, 404);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you prefer to throw an HttpException here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will trigger the custom error page system etc

if ($this->needsDefaultGetOperation($resourceMetadata)) {
$resourceMetadata = $resourceMetadata->withItemOperations(array_merge(
$resourceMetadata->getItemOperations(),
['get' => ['method' => 'GET', 'read' => false, 'serialize' => false, 'output' => ['class' => false], 'controller' => NotFoundAction::class]])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that serialize can be omitted, because the controller throw anyway.

@soyuka
soyuka force-pushed the feature/empty-item-operations branch from 2f3ea1d to 5aa6f20 Compare September 21, 2019 11:40
@soyuka
soyuka merged commit c277aeb into api-platform:master Sep 21, 2019
@dunglas

dunglas commented Sep 24, 2019

Copy link
Copy Markdown
Member

Could you open a docs PR for that @soyuka?

if ($this->needsDefaultGetOperation($resourceMetadata)) {
$resourceMetadata = $resourceMetadata->withItemOperations(array_merge(
$resourceMetadata->getItemOperations(),
['get' => ['method' => 'GET', 'read' => false, 'output' => ['class' => false], 'controller' => NotFoundAction::class]])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you've made a mistake here, it's supposed to be null:

if (false === $attribute) {
return ['class' => null];
}

}

if (null === ($inputOrOutput['class'] ?? null)) {
if (false === ($inputOrOutput['class'] ?? false)) {

@teohhanhui teohhanhui Sep 24, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$itemOperations = $resourceMetadata->getItemOperations();

foreach ($itemOperations as $itemOperation) {
if ('GET' === ($itemOperation['method'] ?? false)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not ?? null instead?

@teohhanhui teohhanhui Sep 24, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, on second thought, this check is unsafe. There might be a custom GET item operation.

The only safe option seems to me to be for the user to declare this get operation themselves:

/**
 * @ApiResource(
 *     itemOperations={
 *         "get"={
 *             "method"="GET",
 *             "controller"=NotFoundAction::class,
 *             "read"=false,
 *             "output"=false,
 *         },
 *     },
 * )
 */

Which to me seems like we should revert and make this a doc entry instead, while providing the NotFoundAction. (I'm of the opinion that we don't need another shortcut to declare this.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could document the custom get operation with one that disables it! I'm fixing what you said!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could document the custom get operation with one that disables it!

What do you mean?

Anyway, I've given it more thought and it's still unsafe anyway. We don't know that there's not already a GET item operation because of route_name. So I really think we must revert this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you said it yourself it's not recommended to use route_name?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but if there's an operation using route_name which is the GET item operation, we could never tell, and we would be creating this get item operation with NotFoundAction. And there's nothing the user could do to fix that.

teohhanhui added a commit to teohhanhui/api-platform-core that referenced this pull request Sep 26, 2019
…y-item-operations"

This reverts commit c277aeb, reversing
changes made to 1088a5d.
@teohhanhui teohhanhui mentioned this pull request Sep 26, 2019
soyuka added a commit that referenced this pull request Sep 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants